; void umbralizar_c (
; 	unsigned char *src,
; 	unsigned char *dst,
; 	int m,
; 	int n,
; 	int row_size,
; 	unsigned char min,
; 	unsigned char max,
; 	unsigned char q
; );

; Parámetros:
; 	rdi = src
; 	rsi = dst
; 	rdx = m
; 	rcx = n
; 	r8 = row_size
; 	r9 = min
; 	rbp + 16 = max
; 	rbp + 24 = q


global umbralizar_asm

doscincocinco: dw 0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF
mascara: DQ 0x0100010001000100, 0x0100010001000100

section .text

umbralizar_asm:
	
		push rbp
		mov rbp, rsp
		push rbx
		push r12
		push r13
		push r14
		push r15


		mov r12, rdi			; guardo ptr al inicio de la matriz en r12, va a ser el i
		mov r13, rsi			; guardo dst en r13
		
		;r9 = min
		;rbp + 16 = max		
		;rbp + 24 = q

		movdqu xmm0, [mascara]
   		movd xmm1, [rbp+16]
    		pshufb xmm1, xmm0 		;obtengo un vector de maximos en word

    		movd xmm2, r9d
    		pshufb xmm2, xmm0 		;obtengo un vector de minimos en word 

		pxor xmm4,xmm4
		movd xmm3, r9d 			
    		pshufb xmm3, xmm4 		;obtengo un vector de maximos en bytes

		mov r14d, edx			; muevo la cantidad de filas a r14
		mov ebx, ecx			; muevo la cantidad de columnas a rbx
		


.inicializoPuntosBorde:
		;los bytes que quedaron sueltos por no entrar en un bloque de 16
		;se analizarán en completarBytes, para eso inizializó acá los reg
		; que vohy a usar:
	
		;r15 va a apuntar al último byte de cada fila src para chequear si se analizó
		xor r15, r15
		mov r15d, ebx; muevo cant cols a r15d
		add r15, r12; le sumo el ptr a la matriz de src
	
		mov rdi, r12;
		mov rsi, r13;

.inicializoContador:

		mov ecx, ebx            
		shr rcx, 4; proceso de a 16 pixels


.ciclo:
		cmp qword rcx, 0		; comparo el contador con 0 para ver si terminé fila
		je .chequeoBytesSueltos		; salta a la siguiente fila

		pxor xmm0, xmm0			; se usara para copiar el resultado de las operaciones
		;movdqu xmm0, [rdi]		; copio 16 bytes a  xmm0

		movdqu xmm4, [rdi]		; copio 16 bytes a  xmm4
		movdqu xmm5, xmm4		; copio 16 bytes a  xmm5
		pxor xmm15, xmm15		; limpio el registro xmm15

		punpcklbw xmm4, xmm15		; desempaqueto la parte baja en xmm4
		punpckhbw xmm5, xmm15		; desempaqueto la parte alta en xmm5
	
		movdqu xmm6, xmm4		; me hago una copia de la parte baja
		movdqu xmm7, xmm5		; me hago una copia de la parte alta
; calculo q

		movd xmm8, [rbp + 24]		; copio Q
		shufps xmm8, xmm8, 0d		; tengo Q en double words
		cvtdq2ps xmm8, xmm8 		; tengo Q en floats

; tomo xmm4 lo desempaqueto y calculo las operaciones en float

		movdqu xmm9, xmm4
		movdqu xmm10, xmm4

;desempaqueto
		punpcklbw xmm9, xmm15		; desempaqueto la parte baja en xmm9
		punpckhbw xmm10, xmm15		; desempaqueto la parte baja en xmm10		

;paso a floats

		cvtdq2ps xmm9, xmm9
		cvtdq2ps xmm10, xmm10
; divido por Q
		divps xmm9, xmm8
		divps xmm10, xmm8

; convierto a entero para recortar

		cvttps2dq xmm9,xmm9
		cvttps2dq xmm10,xmm10

; convierto a floats de nuevo

		cvtdq2ps xmm9,xmm9
		cvtdq2ps xmm10,xmm10

; multiplico por Q

		mulps xmm9, xmm8
		mulps xmm10, xmm8

; convierto a int

		cvttps2dq xmm9,xmm9
		cvttps2dq xmm10,xmm10

; empaqueto el resultado
		packusdw xmm9,xmm10		; tengo el resultado de la parte baja en xmm9



; tomo xmm5 lo desempaqueto y calculo las operaciones en float

		movdqu xmm11, xmm5
		movdqu xmm12, xmm5

;desempaqueto
		punpcklbw xmm11, xmm15		; desempaqueto la parte baja en xmm11
		punpckhbw xmm12, xmm15		; desempaqueto la parte baja en xmm12		

;paso a floats

		cvtdq2ps xmm11, xmm11
		cvtdq2ps xmm12, xmm12
; divido por Q
		divps xmm11, xmm8
		divps xmm12, xmm8

; convierto a entero para recortar

		cvttps2dq xmm11,xmm11
		cvttps2dq xmm12,xmm12

; convierto a floats de nuevo

		cvtdq2ps xmm11,xmm11
		cvtdq2ps xmm12,xmm12

; multiplico por Q

		mulps xmm11, xmm8
		mulps xmm12, xmm8

; convierto a int

		cvttps2dq xmm11,xmm11
		cvttps2dq xmm12,xmm12

; empaqueto el resultado
		packusdw xmm11,xmm12		; tengo el resultado de la parte baja en xmm11

; empaqueto el resultado de las operaciones aritmeticas

		packuswb xmm9, xmm11		; tengo el resultado en xmm9

; 

		movdqu xmm6, xmm4		; me hago una copia de la parte baja
		movdqu xmm7, xmm5		; me hago una copia de la parte alta

		pcmpgtw xmm6, xmm1		; comparo contra el vector max y el result queda en xmm6
		pcmpgtw xmm7, xmm1		; comparo contra el vector max y el result queda en xmm7
		packsswb xmm6,xmm7		; empaqueto el resultado 

		paddusb xmm0, xmm6		; lo guardo en el resultado
;

		movdqu xmm13, xmm4		; me hago una copia de la parte baja
		movdqu xmm14, xmm5		; me hago una copia de la parte alta

		pcmpgtw xmm13, xmm2		; comparo contra el vector min y el result queda en xmm13
		pcmpgtw xmm14, xmm2		; comparo contra el vector min y el result queda en xmm14

		packsswb xmm13, xmm14		; empaqueto el resultado en xmm13

		pxor xmm13, xmm6		; comparo contra los maximos el vector de los minimos

; calculo para filtrar en bytes

		movdqu xmm15, [rdi]		; copio 16 bytes de la imagen
		pcmpeqb xmm15, xmm3		;

;

		por xmm13, xmm15		; saco los que son iguales al minimo

;
		pand xmm9, xmm13		; y hago and con el que tiene las operaciones aritmeticas
		paddusb xmm0, xmm9		; lo sumo al resultado

		movdqu [rsi], xmm0		; muevo al destino los 16 bytes de xmm0
	
		add rdi, 16			; me adelanto 16 bytes para agarrar el siguiente bloque
		add rsi, 16			; me adelanto 16 bytes para guardar el siguiente bloque
		
		sub rcx, 1
		jmp .ciclo



.chequeoBytesSueltos:
		;voy a chequear si la matriz no es multiplo de 4 y me quedaron
		;bytes sueltos.
		cmp r15, rdi; quiero ver si la pos apuntada por r15 > rdi, para ver
		;si aplico padding. Es decir, si me quedaron bytes colgados
		jg .completarBytes
		
.siguienteFila:	
	
		sub r14, 1
		cmp r14, 0
		je .fin	
	
		add r12, r8
		add r13, r8

		jmp .inicializoPuntosBorde
	
.completarBytes:
		xor rdi, rdi;
		xor rsi, rsi;

		mov edi, ebx; muevo a rdi el n
		add rdi, r12; le sumo el ptr al comienzo de la fila actual
		sub rdi, 16; le resto 4
		mov esi, ebx; muevo rsi el n
		add rsi, r13; le sumo el ptr al comienzo de dst
		sub rsi, 16; le resto 4
		add rcx,1 ;para que no salte error cuando vuelva al ciclo main
		;ahora rellené los bytes que me habían quedado colgados, puedo
		;pasar a la siguiente fila
		jmp .ciclo



.fin:

		pop r15
		pop r14
		pop r13
		pop r12
		pop rbx
		pop rbp

		ret
